package com.kh.pajx.sop.util.page;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.kh.pajx.sop.base.IBaseDao;
import com.kh.pajx.sop.base.IBaseService;
import com.kh.pajx.sop.domain.HsSchoolInfo;
import com.kh.pajx.sop.domain.HsSchoolRelation;
import com.kh.pajx.sop.domain.PageBean;
import com.opensymphony.xwork2.ActionContext;

/**
 * 拼接多表分页查询用HQL语句辅助类
 * @version 3.0
 * @author:	azzcsimp
 * @Createdate:	2014年7月26日 下午2:34:05
 */
public class QueryHelperForManyTables {
	
	// =======================常量================================
	/** HQL多表查询-内连接 */
	public static final String INNER_JOIN = "INNER JOIN"; // 可简写为 join  使用with关键字(SQL中用on)	

	/** HQL多表查询-左外连接 */
	public static final String LEFT_OUTER_JOIN = "LEFT OUTER JOIN"; // 可简写为 left join ... with...

	/** HQL多表查询-又外连接 */
	public static final String RIGHT_OUTER_JOIN = "RIGHT OUTER JOIN"; // 可简写为 right join ... with...

	/** HQL多表查询-全连接 */
	public static final String FULL_JOIN = "FULL JOIN";
	
	
	// =======================变量================================
	/** SELECT子句  (必须) */
	private String selectClause = "";

	/** FROM子句(必须) */
	private String fromClause = "";

	/** With子句 (使用多表联合查询必须，反之可选) */
	private String withClause = "";

	/** Where子句(可选) */
	private String whereClause = "";

	/** Order by子句(可选) */
	private String orderByClause = "";

	/** 用于存放表索引与表别名的map */
	private Map<Integer, String> tableIndexMap = new HashMap<Integer, String>();

	/** 参数列表 */
	private List<Object> parameters = new ArrayList<Object>();

	//===========================================================================
	
	/**
	 * 生成FROM子句
	 * @param clazz 查询对象
	 * @param alias 别名
	 * @author: azzcsimp
	 * @Createdate: 2014年6月12日 下午3:58:01
	 */
	public QueryHelperForManyTables(Class clazz, String alias) {
		fromClause = " FROM " + clazz.getSimpleName() + " " + alias;
		tableIndexMap.put(0, alias);
	}
	
	/**
	 * 添加多表 并记录索引, 每使用一次索引加1
	 * @param clazz 查询对象
	 * @param alias 别名
	 * @return this
	 * @author:	azzcsimp
	 * @Createdate:	2014年6月27日 上午10:08:39
	 */
	public QueryHelperForManyTables addTable(Class clazz, String alias) {
		fromClause += "," + clazz.getSimpleName() + " " + alias;
		tableIndexMap.put(tableIndexMap.size(), alias);
		return this;
	}
	
	/**
	 * 生成SELECT子句，默认别名为第一个对象(表)的别名
	 * @param column 查询子项(对应数据库的列)
	 * @return   this
	 * @author:	azzcsimp
	 * @Createdate:	2014年7月26日 下午2:52:52
	 */
	public QueryHelperForManyTables addColumns(String... column){
		return addColumns(0, column);
	}
	
	/**
	 * 生成SELECT子句，根据添加表的顺序索引(从0开始)指定查询子项(对应数据库的列)
	 * @param tableIndex 当前表的添加索引，用于获取对象(表)别名
	 * @param column 查询子项(对应数据库的列)
	 * @return   this
	 * @author:	azzcsimp
	 * @Createdate:	2014年7月26日 下午2:53:41
	 */
	public QueryHelperForManyTables addColumns(int tableIndex, String... column){
		if(selectClause.length() == 0){
			selectClause = "SELECT ";
		}
		
		if (column.length > 0) {
			selectClause += ",";
		} else {
			selectClause += ((selectClause.length() > 7) ? "," : "")
					+ tableIndexMap.get(tableIndex);
		}

		// 拼接SELECT子句
		for (int i = 0; i < column.length; i++) {
			selectClause = selectClause + tableIndexMap.get(tableIndex) + "."
					+ column[i] + ((column.length - 1 - i) != 0 ? "," : "");
		}

		return this;
	}
	
	/**
	 * 添加两属性相等where条件
	 * @param firstTableIndex 两对象关联中第一个对象(表)添加的索引值 
	 * @param firstColumnName 两对象关联中第一个对象(表)的属性(列)
	 * @param secondTableIndex 两对象关联中第二个对象(表)添加的索引值 
	 * @param secondColumnName 两对象关联中第二个对象(表)的属性(列)
	 * @return   
	 * @author:	azzcsimp
	 * @Createdate:	2014年6月30日 下午5:04:37
	 */
	public QueryHelperForManyTables addColumns(int firstTableIndex,
			String firstColumnName, int secondTableIndex,
			String secondColumnName) {
		if (whereClause.length() == 0) {
			whereClause += " WHERE ";
		} else {
			whereClause += " AND ";
		}
		whereClause += tableIndexMap.get(firstTableIndex) + "." + firstColumnName
				+ "=" + tableIndexMap.get(secondTableIndex) + "."
				+ secondColumnName;
		return this;
	}
	
	/**
	 * 获取参数列表，与HQL过滤条件中的'?'一一对应
	 * 
	 * @return
	 */
	public List<Object> getParameters() {
		return parameters;
	}
	
	/**
	 * 获取生成的用于查询数据列表的HQL语句
	 * @return   
	 * @author:	azzcsimp
	 * @Createdate:	2014年6月26日 下午7:56:14
	 */
	public String getListQueryHql() {
		return selectClause + fromClause + withClause + whereClause
				+ orderByClause;
	}

	/**
	 * 获取生成的用于查询总记录数的HQL语句
	 * @return   
	 * @author:	azzcsimp
	 * @Createdate:	2014年6月26日 下午7:58:16
	 */
	public String getCountQueryHql() {
		return "SELECT COUNT(*)" + fromClause + withClause + whereClause
				+ orderByClause;
	}
	
	/**
	 * Dao层封装分页信息，并放到值栈栈顶
	 * 封装具体内容查看PageBean
	 * @see com.kh.pajx.sop.util.page.QueryHelperForManyTables#preparePageBean(com.kh.pajx.sop.base.IBaseService<T>, int, int)
	 * @param dao 持久层方法
	 * @param pageNum 当前页面
	 * @param pageSize 每页显示的数量
	 * @author:	azzcsimp
	 * @Createdate:	2014年6月24日 下午3:07:10
	 */
	@Deprecated
	public void preparePageBean(IBaseDao<?> dao, int pageNum, int pageSize) {
		/*PageBean pageBean = dao.getPageBean(pageNum, pageSize, this);
		ActionContext.getContext().getValueStack().push(pageBean);*/
	}

	/**
	 * Service层封装分页信息，并放到值栈栈顶
	 * 封装具体内容查看PageBean
	 * @param service 业务层方法
	 * @param pageNum 当前页码
	 * @param pageSize 每页显示的数量
	 * @author:	azzcsimp
	 * @Createdate:	2014年6月24日 下午3:07:10
	 */
	public void preparePageBean(IBaseService<?> service, int pageNum,
			int pageSize) {
		/*PageBean pageBean = service.getPageBean(pageNum, pageSize, this);
		ActionContext.getContext().getValueStack().push(pageBean);*/
	}
	
	public static void main(String[] args) {
				new QueryHelperForManyTables(HsSchoolInfo.class, "school")
				.addTable(HsSchoolRelation.class, "relation")
				// addColumns(String... column) 3中用法
				.addColumns()
				//.addColumns("sclName")
				//.addColumns("sclId","sclAddr","sclPhone")
				.addColumns(1)
				.getListQueryHql();
		
	}
}
